package com.katze.boot.applet.asn1.anlysis;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

public abstract class AnalysisHelper extends AnalysisWriter{
    private static final Resource resource = new PathMatchingResourcePatternResolver().getResource("classpath:asn/trans_asn.json");
    private final ObjectMapper objectMapper = new ObjectMapper();

    public void save(Object data) throws IOException {
        super.append(objectMapper.writeValueAsString(read(data)) + "\n");
    }

    public static Resource getResource(){
        return resource;
    }

    protected Map<String, Map<String, String>> load(String filename) throws IOException {
        List<Map<String, String>> nodes = new LinkedList<>();
        Path configDir = resource.getFile().toPath().resolveSibling("config");
        if (filename.endsWith(".asn")){
            AtomicBoolean atomic = new AtomicBoolean(false);
            Files.lines(configDir.resolve(filename)).filter(o -> {
                o = o.trim();
                if (o.length() == 0 || o.startsWith("#")) return false;
                if (o.contains("[BODY]") || o.contains("[TAIL]")){
                    atomic.set(o.contains("[BODY]"));
                    return false;
                }
                return atomic.get();
            }).forEach(o->{
                if (o.contains(",")){
                    if (o.startsWith("tag.")) {
                        o = o.substring(4, o.indexOf("#")).trim();
                        String[] items = o.split(",");
                        Map<String, String> item = new HashMap<>();
                        item.put("id", items[0].substring(0, items[0].indexOf("=")));
                        item.put("length", items[1]);
                        String[] its = items[2].split("!");
                        item.put("type", its[0]);
                        item.put("name", its[1]);
                        nodes.add(item);
                    } else {
                        o = o.substring(0, o.indexOf("#")).trim();
                        String[] items = o.split(",");
                        Map<String, String> item = new HashMap<>();
                        String[] its = items[0].split("=");
                        item.put("name", its[0]);
                        item.put("id", its[1]);
                        item.put("length", items[1]);
                        item.put("type", items[2]);
                        nodes.add(item);
                    }

                }
            });
        } else {
            StringBuilder builder = new StringBuilder();
            Files.lines(configDir.resolve(filename)).forEach(builder::append);
            nodes.addAll(objectMapper.readValue(builder.toString(), new TypeReference<Collection<? extends Map<String, String>>>() {}));
        }
        return nodes.stream().collect(Collectors.toMap(
                o-> o.get("id"),
                o-> o,
                (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u));},
                LinkedHashMap::new
        ));
    }

    protected abstract Map<String, Object> read(Object data) throws IOException;

}
